﻿using System;
using System.Diagnostics.Contracts;
using System.Threading;

namespace MathService
{
    //todo:Переписать, как наследник класса Processor
    public class EventsMonitor : Processor
    {
        /* ------------------------------------------------------------------------------------------ */

        #region События

        public event EventHandler Set;
        public event EventHandler Check;
        public event EventHandler Reset;

        protected virtual void OnSet(EventArgs e)
        {
            var lv_EventHandlers = Set;
            if(lv_EventHandlers != null)
                lv_EventHandlers.Invoke(this, e);
        }

        protected virtual void OnCheck(EventArgs e)
        {
            var lv_EventHandlers = Check;
            if(lv_EventHandlers != null)
                lv_EventHandlers.Invoke(this, e);
        }

        protected virtual void OnReset(EventArgs e)
        {
            var lv_EventHandlers = Reset;
            if(lv_EventHandlers != null)
                lv_EventHandlers.Invoke(this, e);
        }

        private void OnSet() { OnSet(EventArgs.Empty); }
        private void OnCheck() { OnCheck(EventArgs.Empty); }
        private void OnReset() { OnReset(EventArgs.Empty); }

        #endregion

        /* ------------------------------------------------------------------------------------------ */

        private readonly Func<bool> f_CheckPredicate;

        private bool f_State;

        /* ------------------------------------------------------------------------------------------ */

        public bool State { get { return f_State; } }

        /* ------------------------------------------------------------------------------------------ */

        public EventsMonitor(Func<bool> CheckPredicate, int Timeout = 100,
            ThreadPriority Priority = ThreadPriority.Normal)
        {
            Contract.Requires<ArgumentNullException>(CheckPredicate != null);
            Contract.Ensures(f_CheckPredicate != null);

            f_CheckPredicate = CheckPredicate;
            ActionTimeout = Timeout;
            this.Priority = Priority;
        }

        /* ------------------------------------------------------------------------------------------ */

        protected override void MainAction()
        {
            if(f_CheckPredicate())
            {
                if(!f_State)
                {
                    f_State = true;
                    OnSet();
                    OnPropertyChanged("State");
                }
                OnCheck();
            }
            else
            {
                if(f_State)
                {
                    f_State = false;
                    OnReset();
                    OnPropertyChanged("State");
                }
            }
        }

        /* ------------------------------------------------------------------------------------------ */
    }
}
